#include "util.h"
#include "utilc.h"
#include "event_def.h"
#include "util_setting_box.h"
#include "cJSON.h"
#include <sstream>

using namespace util;

CSettingBox       _PlateTypeMap;      //配置中读取的车牌类型
CSettingBox       _PlateTypeNameMap;  //配置中读取的车牌类型名称
CSettingBox       _ColorTypeMap;      //配置中读取的颜色类型
CSettingBox       _ColorTypeNameMap;  //配置中读取的颜色类型名称
CSettingBox       _DirectionNameMap;  //配置中读取的方向名称
CSettingBox       _ForbidTypeMap;     //配置中读取的货车类型
//用来生成违法id
static int             _VioIdServerID = 0;      //配置的服务器id, 1位
static time_t          _VioIdTimetamp = 0;      //时间戳，精确到秒，10位
static int             _VioIdCount = 0;         //同一个时间戳内的计数， 3位
static int             _VioIdRadom = 0;         //随机数， 4位

string plate_type(PLATE_TYPE t){
    static char *tmp[] = {"99", "02", "02", "01"};
    if(t > PLATE_TYPE_BIG)
        t = PLATE_TYPE_UNKNOW;
    return tmp[t];
}

string plate_color(COLOR_TYPE c){
    static char *tmp[] = {"99", "00", "01", "02", "03", "04", "05", "06", "07", "08", "09"};
    if(c > COLOR_WHITE)
        c = COLOR_UNKNOWN;
    return tmp[c];
}

int pic_num(SPassEvent* e) {
    int ret = 0;
    for(int i=0; i<3; i++)
        if(!e->OriginPhoto[0].strURL.empty())
            ret++;
    if(!e->MixPhoto.strURL.empty())
        ret++;
    if(!e->VehiclePhoto.strURL.empty())
        ret++;
    return ret;
}

SPassEvent::SPassEvent()
    : Manuf(CAMERA_MANUF_UNKNOW)
    , strGuid(util::Guid::guid())
    , ePlateType(PLATE_TYPE_UNKNOW)
    , ePlateColor(COLOR_UNKNOWN)
    , eCarColor(COLOR_UNKNOWN)
    , nLane(0)
    , nOriginNum(0)
    , nPlateNum(0)
    , nVioCode("")
    , nSpeed(0)
    , nSpeedLimit(0)
    , nVehiclLen(0)
{
}

//1400接收到的数据
string event14002json(S1400Event *e) {
    stringstream ss;
    ss << "{\"guid\":\"" << e->guid << "\""
        ",\"deviceId\":\"" << e->deviceId << "\""
        ",\"plateNo\":\"" << e->plateNo << "\""
        ",\"plateClass\":\"" << e->plateClass << "\""
        ",\"plateColor\":\"" << e->plateColor << "\"";
    if(!e->passTime.empty())
        ss << ",\"passTime\":\"" << e->passTime << "\"";
    if(!e->vehicleColor.empty())
        ss << ",\"vehicleColor\":\"" << e->vehicleColor << "\"";
    if(e->laneNo > 0)
        ss << ",\"laneNo\":" << e->laneNo;
    if(!e->originPic1.empty())
        ss << ",\"originPic1\":\"" << e->originPic1 << "\"";
    if(!e->originPic2.empty())
        ss << ",\"originPic2\":\"" << e->originPic2 << "\"";
    if(!e->originPic3.empty())
        ss << ",\"originPic3\":\"" << e->originPic3 << "\"";
    if(!e->platePic.empty())
        ss << ",\"platePic\":\"" << e->platePic << "\"";
    if(!e->vehiclePic.empty())
        ss << ",\"vehiclePic\":\"" << e->vehiclePic << "\"";
    if(!e->mixPic.empty())
        ss << ",\"mixPic\":\"" << e->mixPic << "\"";
    if(!e->illegalCode.empty())
        ss << ",\"illegalCode\":\"" << e->illegalCode << "\"";
    if(e->speed > 0)
        ss << ",\"speed\":" << e->speed;
    if(e->speedLimit > 0)
        ss << ",\"speedLimit\":" << e->speedLimit;
    if(e->vehicleLength > 0)
        ss << ",\"vehicleLength\":" << e->vehicleLength;
    if(!e->vehicleClass.empty())
        ss << ",\"vehicleClass\":\"" << e->vehicleClass << "\"";
    ss << "}";
    return ss.str();
}

string event1400s2json(list<S1400Event *> vecEvents) {
    stringstream ss;
    ss << "[";
    bool first = true;
    for(auto e:vecEvents) {
        if(first) {
            first = false;
        } else {
            ss << ",";
        }
        ss << event14002json(e);
    }
    ss << "]";
    return ss.str();
}

static S1400Event* json2event1400(cJSON *jvio) {
    S1400Event* e = new S1400Event();
    for (cJSON *attr = jvio->child; attr; attr = attr->next){
        if(!strcmp(attr->string, "guid")){
            e->guid = attr->valuestring;
        } else if(!strcmp(attr->string, "deviceId")){
            e->deviceId = attr->valuestring;
        } else if(!strcmp(attr->string, "plateNo")){
            e->plateNo = attr->valuestring;
        } else if(!strcmp(attr->string, "plateClass")){
            if(attr->valuestring)
                e->plateClass = attr->valuestring;
            else if(attr->valueint > 0)
                e->plateClass = to_string(attr->valueint);
        } else if(!strcmp(attr->string, "plateColor")){
            e->plateColor = attr->valuestring;
        } else if(!strcmp(attr->string, "vehicleColor")){
            e->vehicleColor = attr->valuestring;
        } else if(!strcmp(attr->string, "passTime")){
            e->passTime = attr->valuestring;
        } else if(!strcmp(attr->string, "laneNo")){
            e->laneNo = attr->valueint;
        } else if(!strcmp(attr->string, "originPic1")){
            e->originPic1 = attr->valuestring;
        } else if(!strcmp(attr->string, "originPic2")){
            e->originPic2 = attr->valuestring;
        } else if(!strcmp(attr->string, "originPic3")){
            e->originPic3 = attr->valuestring;
        } else if(!strcmp(attr->string, "platePic")){
            e->platePic = attr->valuestring;
        } else if(!strcmp(attr->string, "vehiclePic")){
            e->vehiclePic = attr->valuestring;
        } else if(!strcmp(attr->string, "mixPic")){
            e->mixPic = attr->valuestring;
        } else if(!strcmp(attr->string, "illegalCode")){
            e->illegalCode = attr->valuestring;
        } else if(!strcmp(attr->string, "speed")){
            e->speed = attr->valueint;
        } else if(!strcmp(attr->string, "speedLimit")){
            e->speedLimit = attr->valueint;
        } else if(!strcmp(attr->string, "vehicleLength")){
            e->vehicleLength = attr->valueint;
        } else if(!strcmp(attr->string, "vehicleClass")){
            e->vehicleClass = attr->valuestring;
        }
    }
    return e;
}

S1400Event* json2event1400(string msg) {
    cJSON* jmsg = cJSON_Parse(msg.c_str());
    CHECK_POINT_NULLPTR(jmsg);
    S1400Event* e = json2event1400(jmsg);
    cJSON_Delete(jmsg);
    return e;
}

vector<S1400Event *> json2event1400s(string msg) {
    vector<S1400Event *> ret;
    cJSON* jmsg = cJSON_Parse(msg.c_str());
    if(NULL == jmsg || jmsg->type != cJSON_Array){
        Log::error("this msg is not an array");
        cJSON_Delete(jmsg);
        return ret;
    }
    int event_num = cJSON_GetArraySize(jmsg);
    //Log::debug("%d events in this msg", event_num);
    for(int i=0; i<event_num; i++) {
        cJSON *js = cJSON_GetArrayItem(jmsg, i);
        S1400Event *e = json2event1400(js);
        ret.push_back(e);
    }
    cJSON_Delete(jmsg);
    return ret;
}

S1400Event* copy1400Event(S1400Event* e) {
    S1400Event *ret = new S1400Event();
    ret->passTime = e->passTime;
    ret->guid = e->guid;
    ret->deviceId = e->deviceId;
    ret->plateNo = e->plateNo;
    ret->plateClass = e->plateClass;
    ret->plateColor = e->plateColor;
    ret->vehicleColor = e->vehicleColor;
    ret->laneNo = e->laneNo;
    ret->originPic1 = e->originPic1;
    ret->originPic2 = e->originPic2;
    ret->originPic3 = e->originPic3;
    ret->platePic = e->platePic;
    ret->vehiclePic = e->vehiclePic;
    ret->mixPic = e->mixPic;
    ret->illegalCode = e->illegalCode;
    ret->speed = e->speed;
    ret->speedLimit = e->speedLimit;
    ret->vehicleLength = e->vehicleLength;
    ret->vehicleClass = e->vehicleClass;
    return ret;
}

//老系统过车违法
string event2json(SPassEvent *e){
    if(!e->nVioCode.empty() && e->MixPhoto.strURL.empty())
        e->MixPhoto.strURL = e->OriginPhoto[0].strURL;
	stringstream ss;
	ss << "{\"Manuf\":" << e->Manuf
        << ",\"strGuid\":\"" << e->strGuid << "\""
		<< ",\"strDevID\":\"" << e->strDevID << "\""
		<< ",\"strDevType\":\"" << e->strDevType << "\""
		<< ",\"strDevDirection\":\"" << e->strDevDirection << "\""
		<< ",\"strAgency\":\"" << e->strAgency << "\""
		<< ",\"strUser\":\"" << e->strUser <<"\""
		<< ",\"strEventTime\":\"" << e->strEventTime << "\""
		<< ",\"strPlate\":\"" << e->strPlate << "\""
		<< ",\"ePlateType\":" << e->ePlateType
		<< ",\"ePlateColor\":" << e->ePlateColor
		<< ",\"eCarColor\":" << e->eCarColor
		<< ",\"nLane\":" << e->nLane
		<< ",\"OriginPhoto1\":\"" << e->OriginPhoto[0].strURL << "\""
		<< ",\"OriginPhoto2\":\"" << e->OriginPhoto[1].strURL << "\""
		<< ",\"OriginPhoto3\":\"" << e->OriginPhoto[2].strURL << "\""
		<< ",\"PlatePhoto\":\"" << e->PlatePhoto.strURL << "\""
		<< ",\"VehiclePhoto\":\"" << e->VehiclePhoto.strURL << "\""
		<< ",\"MixPhoto\":\"" << e->MixPhoto.strURL << "\""
		<< ",\"nVioCode\":" << e->nVioCode
		<< ",\"nSpeed\":" << e->nSpeed
		<< ",\"nSpeedLimit\":" << e->nSpeedLimit
		<< ",\"nVehiclLen\":" << e->nVehiclLen
		<< "}";
	return ss.str();
}

SPassEvent* json2event(cJSON *jvio){
	SPassEvent *vio = new SPassEvent();
        for (cJSON *attr = jvio->child; attr; attr = attr->next){
			if(!strcmp(attr->string, "Manuf")){
				vio->Manuf = (CAMERA_MANUF)attr->valueint;
            } else if(!strcmp(attr->string,"strGuid")){
                vio->strGuid = string(attr->valuestring);
            } else if(!strcmp(attr->string,"strDevID")){
                vio->strDevID = string(attr->valuestring);
            } else if(!strcmp(attr->string,"strDevType")){
                vio->strDevType = string(attr->valuestring);
            } else if(!strcmp(attr->string,"strDevDirection")){
                vio->strDevDirection = string(attr->valuestring);
            } else if(!strcmp(attr->string,"strAgency")){
				vio->strAgency = string(attr->valuestring);
            } else if(!strcmp(attr->string,"strUser")){
                vio->strUser = string(attr->valuestring);
            } else if(!strcmp(attr->string,"strEventTime")){
                vio->strEventTime = string(attr->valuestring);
            } else if(!strcmp(attr->string,"strPlate")){
                vio->strPlate = string(attr->valuestring);
            } else if(!strcmp(attr->string,"ePlateType")){
                vio->ePlateType = (PLATE_TYPE)attr->valueint;
            } else if(!strcmp(attr->string,"ePlateColor")){
                vio->ePlateColor = (COLOR_TYPE)attr->valueint;
            } else if(!strcmp(attr->string,"eCarColor")){
				vio->eCarColor = (COLOR_TYPE)attr->valueint;
            } else if(!strcmp(attr->string,"nLane")){
                vio->nLane = attr->valueint;
            } else if(!strcmp(attr->string,"OriginPhoto1")){
                vio->OriginPhoto[0].strURL = string(attr->valuestring);
            } else if(!strcmp(attr->string,"OriginPhoto2")){
                vio->OriginPhoto[1].strURL  = string(attr->valuestring);
            } else if(!strcmp(attr->string,"OriginPhoto3")){
                vio->OriginPhoto[2].strURL  = string(attr->valuestring);
            } else if(!strcmp(attr->string,"PlatePhoto")){
				vio->PlatePhoto.strURL = string(attr->valuestring);
            } else if(!strcmp(attr->string,"VehiclePhoto")){
                vio->VehiclePhoto.strURL = string(attr->valuestring);
            } else if(!strcmp(attr->string,"MixPhoto")){
                vio->MixPhoto.strURL = string(attr->valuestring);
            } else if(!strcmp(attr->string,"nVioCode")){
                vio->nVioCode = attr->valueint;
            } else if(!strcmp(attr->string,"nSpeed")){
                vio->nSpeed = attr->valueint;
            } else if(!strcmp(attr->string,"nSpeedLimit")){
                vio->nSpeedLimit = attr->valueint;
            } else if(!strcmp(attr->string,"nVehiclLen")){
                vio->nVehiclLen = attr->valueint;
            }
        }

        return vio;
}

vector<SPassEvent*> json2event(string msg, bool vio){
    vector<SPassEvent*> ret;
    cJSON* jmsg = cJSON_Parse(msg.c_str());
    CHECK_POINT(jmsg, ret);
    //cJSON* jtype = cJSON_GetObjectItem(jmsg,"root");
    //if(!vio && (NULL == jtype || strcmp(jtype->valuestring, "passevent"))){
    //    Log::error("this is not a car json");
    //    cJSON_Delete(jmsg);
    //    return ret;
    //}
    cJSON* jCtx = cJSON_GetObjectItem(jmsg,"events");
    if(NULL == jCtx || jCtx->type != cJSON_Array){
        Log::error("no event array node");
        cJSON_Delete(jmsg);
        return ret;
    }
    int event_num = cJSON_GetArraySize(jCtx);
    Log::debug("%d events in this msg", event_num);
    for(int i=0; i<event_num; i++) {
        cJSON *js = cJSON_GetArrayItem(jCtx, i);
        SPassEvent *e = json2event(js);
        ret.push_back(e);
    }
    cJSON_Delete(jmsg);
    return ret;
}

COLOR_TYPE checkColor(string tmp) {
    if(tmp == "1")
        return COLOR_TYPE::COLOR_BLACK;
    else if(tmp == "2")
        return COLOR_TYPE::COLOR_WHITE;
    else if(tmp == "3")
        return COLOR_TYPE::COLOR_GRAY;
    else if(tmp == "4")
        return COLOR_TYPE::COLOR_RED;
    else if(tmp == "5")
        return COLOR_TYPE::COLOR_BLUE;
    else if(tmp == "6")
        return COLOR_TYPE::COLOR_YELLOW;

    return COLOR_TYPE::COLOR_UNKNOWN;
}

PLATE_TYPE checkPlate(string tmp) {
    if(tmp == "01")
        return PLATE_TYPE::PLATE_TYPE_BIG;
    else if(tmp == "02")
        return PLATE_TYPE::PLATE_TYPE_SMALL;

    return PLATE_TYPE::PLATE_TYPE_UNKNOW;
}

SPassEvent* transEvent(S1400Event *e, SCameraInfo *cam) {
    SPassEvent* ret = new SPassEvent();
    ret->strGuid = e->guid;
    ret->strDevID = cam->id;
    ret->strDevType = cam->type;
    ret->strDevDirection = cam->dir;
    ret->strAgency = cam->agency;
    ret->strUser = cam->usr;
    ret->strEventTime = e->passTime;
    if(ret->strEventTime.size() < 17) {
        int num = 17-e->passTime.size();
        for(int i=0; i<num; i++)
            ret->strEventTime.push_back('0');
    }
    ret->strPlate = e->plateNo;
    ret->ePlateType = checkPlate(e->plateClass);
    ret->ePlateColor = checkColor(e->plateColor);
    ret->eCarColor = checkColor(e->vehicleColor);
    ret->nLane = e->laneNo;
    ret->nOriginNum = (e->originPic1.empty()?0:1)
                    + (e->originPic2.empty()?0:1)
                    + (e->originPic3.empty()?0:1);
    ret->OriginPhoto[0].strURL = e->originPic1;
    ret->OriginPhoto[1].strURL = e->originPic2;
    ret->OriginPhoto[2].strURL = e->originPic3;
    ret->PlatePhoto.strURL = e->platePic;
    ret->VehiclePhoto.strURL = e->vehiclePic;
    ret->MixPhoto.strURL = e->mixPic;
    ret->nVioCode = e->illegalCode;
    ret->nSpeed = e->speed;
    ret->nSpeedLimit = e->speedLimit;
    ret->nVehiclLen = e->vehicleLength;
    return ret;
}

//新系统违法
string newViolation2json(SNewViolation *e) {
    stringstream ss;
    ss << "{\"plate\": \"" << e->plate << "\","
        "\"id\":" << e->id << ","
        "\"plateTypeId\":\"" << e->plateTypeId << "\","
        "\"plateColorId\":\"" << e->plateColorId << "\","
        "\"facilityId\":" << e->facilityId << ","
        "\"lane\":" << e->lane << ","
        "\"deviceTypeId\":\"" << e->deviceTypeId << "\","
        "\"violationTime\":\"" << e->violationTime << "\","
        "\"violationTypeId\":\"" << e->violationTypeId << "\"";
    if(e->realValue != 0)
        ss << ",\"realValue\":" << e->realValue;
    if(e->standardValue != 0)
        ss << ",\"standardValue\":" << e->standardValue;
    ss << ",\"pictureNumber\":" << e->pictureNumber;
    if(!e->pictureLink0.empty())
        ss << ",\"pictureLink0\":\"" << e->pictureLink0 << "\"";
    else if(!e->pictureLink1.empty())
        ss << ",\"pictureLink0\":\"" << e->pictureLink1 << "\"";
    if(!e->pictureLink1.empty())
        ss << ",\"pictureLink1\":\"" << e->pictureLink1 << "\"";
    if(!e->pictureLink2.empty())
        ss << ",\"pictureLink2\":\"" << e->pictureLink2 << "\"";
    if(!e->pictureLink3.empty())
        ss << ",\"pictureLink3\":\"" << e->pictureLink3 << "\"";
    if(!e->pictureLink4.empty())
        ss << ",\"pictureLink4\":\"" << e->pictureLink4 << "\"";
    ss << "}";
    return ss.str();
}

//从yyyymmddhhmiss[xxx] => yyyy-mm-dd hh:mi:ss
string formatTime(string str) {
    if(str.size() < 14)
        return CTimeFormat::printNow("%Y-%m-%d %H:%M:%S");
    stringstream ss;
    ss << str.substr(0,4) << "-" << str.substr(4,2) << "-" << str.substr(6,2) << " "
        << str.substr(8,2) << ":" << str.substr(10, 2) << ":" << str.substr(12, 2);
    return ss.str();
}

//从yyyymmddhhmiss[xxx] => yyyymmdd
string formatDateKey(string str) {
    if(str.size() < 8)
        return CTimeFormat::printNow("%Y%m%d");
    return str.substr(0,8);
}

SNewViolation* transNewViolation(S1400Event *e, SFacility *fac) {
    SNewViolation* ret = new SNewViolation();
    if(_VioIdTimetamp == 0 || _VioIdCount > 9999) {
         time_t now = time(NULL);
         if(now <= _VioIdTimetamp)
             _VioIdTimetamp++;
         else
             _VioIdTimetamp = now;
        _VioIdCount = 0;
    }
    _VioIdRadom = rand() % 1000;
    char szGenID[20] = {0};
    sprintf(szGenID, "%01d%010d%04d%03d", _VioIdServerID, _VioIdTimetamp, _VioIdCount++, _VioIdRadom);
    ret->id              = szGenID;
    ret->facilityId      = fac->facilityId;
    ret->deviceTypeId    = fac->deviceTypeId;
    ret->plate           = e->plateNo;
    ret->plateTypeId     = _PlateTypeMap.GetValue(e->plateClass);
    if(e->plateClass == "51") e->plateColor = 90; //大型新能源车，车牌颜色转为黄绿
    if(e->plateClass == "52") e->plateColor = 9; //小型新能源车， 车牌颜色转为绿
    ret->plateColorId    = _ColorTypeMap.GetValue(e->plateColor);
    ret->lane            = e->laneNo;
    ret->violationTime   = formatTime(e->passTime);
    ret->violationTypeId = e->illegalCode;
    ret->realValue       = e->speed;
    ret->standardValue   = e->speedLimit;
    ret->pictureNumber   = (e->mixPic.empty()?0:1)
                         + (e->originPic1.empty()?0:1)
                         + (e->originPic2.empty()?0:1)
                         + (e->originPic3.empty()?0:1)
                         + (e->vehiclePic.empty()?0:1);
    ret->pictureLink0    = e->mixPic;
    ret->pictureLink1    = e->originPic1;
    ret->pictureLink2    = e->originPic2;
    ret->pictureLink3    = e->originPic3;
    ret->pictureLink4    = e->vehiclePic;
    return ret;
}

SNewViolation* transNewViolation(SPassEvent *e, SFacility *fac) {
    SNewViolation* ret = new SNewViolation();
    if(_VioIdTimetamp == 0 || _VioIdCount > 9999) {
        time_t now = time(NULL);
        if(now <= _VioIdTimetamp)
            _VioIdTimetamp++;
        else
            _VioIdTimetamp = now;
        _VioIdCount = 0;
    }
    _VioIdRadom = rand() % 1000;
    char szGenID[20] = {0};
    sprintf(szGenID, "%01d%010d%04d%03d", _VioIdServerID, _VioIdTimetamp, _VioIdCount++, _VioIdRadom);
    ret->id              = szGenID;
    ret->facilityId      = fac->facilityId;
    ret->deviceTypeId    = e->strDevType;//fac->deviceTypeId;
    ret->plate           = e->strPlate;
    ret->plateTypeId     = _PlateTypeMap.GetValue(e->ePlateType);
    ret->plateColorId    = _ColorTypeMap.GetValue(e->ePlateColor);
    ret->lane            = (e->nLane >= 10) ? (e->nLane - 10) : e->nLane;
    ret->violationTime   = formatTime(e->strEventTime);
    ret->violationTypeId = e->nVioCode;
    ret->realValue       = e->nSpeed;
    ret->standardValue   = e->nSpeedLimit;
    ret->pictureNumber   = (e->OriginPhoto[0].strURL.empty()?0:1)
        + (e->OriginPhoto[1].strURL.empty()?0:1)
        + (e->OriginPhoto[2].strURL.empty()?0:1)
        + (e->MixPhoto.strURL.empty()?0:1)
        + (e->VehiclePhoto.strURL.empty()?0:1);
    ret->pictureLink0    = e->MixPhoto.strURL;
    ret->pictureLink1    = e->OriginPhoto[0].strURL;
    ret->pictureLink2    = e->OriginPhoto[1].strURL;
    ret->pictureLink3    = e->OriginPhoto[2].strURL;
    ret->pictureLink4    = e->VehiclePhoto.strURL;
    return ret;
}

//新系统过车
string newPass2Json(SNewPass *e) {
    stringstream ss;
    ss << "{\"facilityId\":" << e->facilityId << ","
        "\"deviceTypeId\":\"" << e->deviceTypeId << "\","
        "\"deviceTypeName\":\"" << e->deviceTypeName << "\","
        "\"dateKey\":\"" << e->dateKey << "\","
        "\"passTime\":\"" << e->passTime << "\","
        "\"plate\":\"" << e->plate << "\","
        "\"plateTypeCode\":\"" << e->plateTypeCode << "\","
        "\"plateTypeName\":\"" << e->plateTypeName << "\","
        "\"plateColorCode\":\"" << e->plateColorCode << "\","
        "\"plateColorName\":\"" << e->plateColorName << "\","
        "\"directionID\":\"" << e->direction << "\","
        "\"directionName\":\"" << e->directionName << "\","
        "\"lane\":" << e->lane;
    if(e->speed != 0)
        ss << ",\"speed\":" << e->speed;
    if(e->length != 0)
        ss << ",\"length\":" << e->length;
    if(!e->pictureLink1.empty())
        ss << ",\"pictureLink1\":\"" << e->pictureLink1 << "\"";
    if(!e->pictureLink2.empty())
        ss << ",\"pictureLink2\":\"" << e->pictureLink2 << "\"";
    if(!e->pictureLink3.empty())
        ss << ",\"pictureLink3\":\"" << e->pictureLink3 << "\"";
    if(!e->lon.empty())
        ss << ",\"lon\":" << e->lon;
    if(!e->lat.empty())
        ss << ",\"lat\":" << e->lat;
    if(!e->ip.empty())
        ss << ",\"ip\":\"" << e->ip << "\"";
    if(!e->location.empty())
        ss << ",\"location\":\"" << e->location << "\"";
    if(!e->forbidTypeId.empty())
        ss << ",\"forbidTypeId\":\"" << e->forbidTypeId << "\"";
    ss << "}";
    return ss.str();
}

string newPasses2Json(list<SNewPass*> vecEvents) {
    stringstream ss;
    ss << "[";
    bool first = true;
    for(auto e:vecEvents) {
        if(first) {
            first = false;
        } else {
            ss << ",";
        }
        ss << newPass2Json(e);
    }
    ss << "]";
    return ss.str();
}

SNewPass* transNewPass(S1400Event *e, SFacility *fac) {
    SNewPass* ret = new SNewPass();
    ret->facilityId     = fac->facilityId;
    ret->deviceTypeId   = fac->deviceTypeId;
    ret->deviceTypeName = fac->deviceTypeName;
    ret->direction      = fac->drection;
    ret->directionName  = _DirectionNameMap.GetValue(fac->drection);
    ret->dateKey        = formatDateKey(e->passTime);
    ret->plate          = e->plateNo;
    ret->plateTypeCode  = _PlateTypeMap.GetValue(e->plateClass);
    ret->plateTypeName  = _PlateTypeNameMap.GetValue(e->plateClass);
    ret->plateColorCode = _ColorTypeMap.GetValue(e->plateColor);
    ret->plateColorName = _ColorTypeNameMap.GetValue(e->plateColor);
    ret->lane           = e->laneNo;
    ret->speed          = e->speed;
    ret->length         = e->vehicleLength;
    ret->pictureLink1   = e->originPic1;
    ret->pictureLink2   = e->vehiclePic;
    ret->pictureLink3   = e->platePic;
    ret->lon            = fac->lon;
    ret->lat            = fac->lat;
    ret->ip             = fac->ip;
    ret->location       = fac->location;
    ret->passTime       = formatTime(e->passTime);
    ret->violationTypeId= e->illegalCode;
    ret->forbidTypeId   = _ForbidTypeMap.GetValue(e->vehicleClass);
    return ret;
}

SNewPass* transNewPass(SPassEvent *e, SFacility *fac) {
    SNewPass* ret = new SNewPass();
    ret->facilityId     = fac->facilityId;
    ret->deviceTypeId   = fac->deviceTypeId;
    ret->deviceTypeName = fac->deviceTypeName;
    ret->direction      = fac->drection;
    ret->directionName  = _DirectionNameMap.GetValue(fac->drection);
    ret->dateKey        = formatDateKey(e->strEventTime);
    ret->plate          = e->strPlate;
    ret->plateTypeCode  = _PlateTypeMap.GetValue(e->ePlateType);
    ret->plateTypeName  = _PlateTypeNameMap.GetValue(e->ePlateType);
    ret->plateColorCode = _ColorTypeMap.GetValue(e->ePlateColor);
    ret->plateColorName = _ColorTypeNameMap.GetValue(e->ePlateColor);
    ret->lane           = (e->nLane >= 10) ? (e->nLane - 10) : e->nLane;
    ret->speed          = e->nSpeed;
    ret->length         = e->nVehiclLen;
    ret->pictureLink1   = e->OriginPhoto[0].strURL;
    ret->pictureLink2   = e->VehiclePhoto.strURL;
    ret->pictureLink3   = e->PlatePhoto.strURL;
    ret->lon            = fac->lon;
    ret->lat            = fac->lat;
    ret->ip             = fac->ip;
    ret->location       = fac->location;
    ret->passTime       = formatTime(e->strEventTime);
    ret->violationTypeId= "0";
    ret->forbidTypeId   = "";
    return ret;
}

SNewPass* copyNewPass(SNewPass* e) {
    SNewPass* ret = new SNewPass();
    ret->facilityId     = e->facilityId;
    ret->deviceTypeId   = e->deviceTypeId;
    ret->deviceTypeName = e->deviceTypeName;
    ret->direction      = e->direction;
    ret->directionName  = e->directionName;
    ret->dateKey        = e->dateKey;
    ret->plate          = e->plate;
    ret->plateTypeCode  = e->plateTypeCode;
    ret->plateTypeName  = e->plateTypeName;
    ret->plateColorCode = e->plateColorCode;
    ret->plateColorName = e->plateColorName;
    ret->lane           = e->lane;
    ret->speed          = e->speed;
    ret->length         = e->length;
    ret->pictureLink1   = e->pictureLink1;
    ret->pictureLink2   = e->pictureLink2;
    ret->pictureLink3   = e->pictureLink3;
    ret->lon            = e->lon;
    ret->lat            = e->lat;
    ret->ip             = e->ip;
    ret->location       = e->location;
    ret->passTime       = e->passTime;
    ret->violationTypeId= e->violationTypeId;
    ret->forbidTypeId   = e->forbidTypeId;
    return ret;
}

static SNewPass* json2eventnew(cJSON *jvio) {
    SNewPass* e = new SNewPass();
    for (cJSON *attr = jvio->child; attr; attr = attr->next){
        if(!strcmp(attr->string, "facilityId")){
            e->facilityId = to_string(attr->valueint);
        } else if(!strcmp(attr->string, "deviceTypeId")){
            e->deviceTypeId = attr->valuestring;
        } else if(!strcmp(attr->string, "deviceTypeName")){
            e->deviceTypeName =attr->valuestring;
        } else if(!strcmp(attr->string, "dateKey")){
            e->dateKey = attr->valuestring;
        } else if(!strcmp(attr->string, "passTime")){
            e->passTime = attr->valuestring;
        } else if(!strcmp(attr->string, "plate")){
            e->plate = attr->valuestring;
        } else if(!strcmp(attr->string, "plateTypeCode")){
            e->plateTypeCode = attr->valueint;
        } else if(!strcmp(attr->string, "plateTypeName")){
            e->plateColorName = attr->valuestring;
        } else if(!strcmp(attr->string, "plateColorCode")){
            e->plateColorCode = attr->valuestring;
        } else if(!strcmp(attr->string, "plateColorName")){
            e->plateColorName = attr->valuestring;
        } else if(!strcmp(attr->string, "directionID")){
            e->direction = attr->valuestring;
        } else if(!strcmp(attr->string, "directionName")){
            e->directionName = attr->valuestring;
        } else if(!strcmp(attr->string, "lane")){
            e->lane = attr->valueint;
        } else if(!strcmp(attr->string, "speed")){
            e->speed = attr->valueint;
        } else if(!strcmp(attr->string, "length")){
            e->length = attr->valueint;
        } else if(!strcmp(attr->string, "pictureLink1")){
            e->pictureLink1 = attr->valuestring;
        } else if(!strcmp(attr->string, "pictureLink2")){
            e->pictureLink2 = attr->valuestring;
        } else if(!strcmp(attr->string, "pictureLink3")){
            e->pictureLink3 = attr->valuestring;
        } else if(!strcmp(attr->string, "lon")){
            e->lon = to_string(attr->valuedouble);
        } else if(!strcmp(attr->string, "lat")){
            e->lat = to_string(attr->valuedouble);
        } else if(!strcmp(attr->string, "ip")){
            e->ip = attr->valuestring;
        } else if(!strcmp(attr->string, "location")){
            e->location = attr->valuestring;
        } else if(!strcmp(attr->string, "forbidTypeId")){
            e->forbidTypeId = attr->valuestring;
        }
    }
    return e;
}

vector<SNewPass*> json2eventnews(string msg) {
    vector<SNewPass *> ret;
    cJSON* jmsg = cJSON_Parse(msg.c_str());
    if(NULL == jmsg || jmsg->type != cJSON_Array){
        Log::error("this msg is not an array");
        cJSON_Delete(jmsg);
        return ret;
    }
    int event_num = cJSON_GetArraySize(jmsg);
    //Log::debug("%d events in this msg", event_num);
    for(int i=0; i<event_num; i++) {
        cJSON *js = cJSON_GetArrayItem(jmsg, i);
        SNewPass *e = json2eventnew(js);
        ret.push_back(e);
    }
    cJSON_Delete(jmsg);
    return ret;
}

void readConfigType() {
    //从配置文件读取字典设置
    _PlateTypeMap.ReadValues("PlateType");
    _PlateTypeNameMap.ReadValues("PlateTypeName");
    _ColorTypeMap.ReadValues("PlateColor");
    _ColorTypeNameMap.ReadValues("PlateColorName");
    _DirectionNameMap.ReadValues("DirectionName");
    _ForbidTypeMap.ReadValues("ForbidType");
    Log::debug("read dict success");

    //初始化
    srand((int)time(0));
    _VioIdServerID = Settings::getValue("Server", "id", 0);
}